// 创建 用户 pinia存储(仓库)
import { defineStore } from "pinia";
import { reqLogin, reqUserInfo, reqLogout } from "@/api/user";
import type { loginForm, loginResponseData,userResponseData } from "@/api/user/type";
import type { UserState } from "./types/type";
import { SET_TOKEN, GET_TOKEN, REMOVE_TOKEN } from "@/utils/token";
import { constRoutes,asyncRoute,anyRoute } from "@/router/routers";
import router from "@/router";
//@ts-ignore
import cloneDeep from 'lodash/cloneDeep'

function filterAsyncRoute(asyncRoute:any,routes:any){
    return asyncRoute.filter((item:any)=>{
        if(routes.includes(item.name)){
            if(item.children && item.children.length>0){
                item.children = filterAsyncRoute(item.children,routes)
            }
            return true
        }
    })
}

let useUserStore = defineStore('User', {
    // 存储
    state: (): UserState => {
        return {
            //     //tokenPiniaStore初始值 来自 浏览器本地持久化存储
            token: GET_TOKEN(), //后端登录接口返回的 用户唯一标识token
            menuRoutes: constRoutes, //常量路由放入piniaStore中,
            username: '',
            avatar: '',
            //存储当前用户是否包含某一个按钮
            buttons:[],
        }
    },
    actions: {
        async userLogin(data: loginForm) {
            let result: loginResponseData = await reqLogin(data)
            if (result.code == 200) {
                //登录成功, 则 '后端登录接口返回的 用户唯一标识token' 保存到 pinia 中
                // this.token = (result.token as string);
                this.token = (result.data as string);
                //由于pinia或vuex存储是放在浏览器当前页面的js变量中的，因此刷新页面则丢失
                //所以 需要 在 浏览器的本地持久存储 中 再 存储  '后端登录接口返回的 用户唯一标识token'
                // SET_TOKEN(result.token as string)
                SET_TOKEN(result.data as string)
                return 'ok'
            } else {
                return Promise.reject(new Error(result.message))
                //登录失败
                /*
                视频课 https://www.bilibili.com/video/BV1Xh411V7b5?t=1574.1&p=32 中写的是:
                return Promise.reject(new Error(result.data.message)); 这样写不对，因为:
                  1. 同一个函数中的return语句应该返回同类型的值，所以这里应该返回boolean值
                  2. 返回类型不需要再用Promise包裹了, 因为调用方拿到的返回值类型已经是Promise<boolean>
                 */
            }
        },
        //访问后端获取用户信息接口，然后写入pinia存储
        async userInfo() {

            //获取用户信息 放到 pinia存储(本UserStore) 中
            let result: userResponseData = await reqUserInfo()

            if (result.code == 200) {
                //接口访问正常
                this.username = result.data.name
                this.avatar = result.data.avatar
                this.buttons = result.data.buttons
                let userAsyncRoute = filterAsyncRoute(cloneDeep(asyncRoute ),result.data.routes)
                this.menuRoutes = [...constRoutes,...userAsyncRoute,...anyRoute];
                [...userAsyncRoute,...anyRoute].forEach((route:any)=>{
                    router.addRoute(route)
                })
                return 'ok'
            } else {
                return Promise.reject(new Error(result.message));
            }
        },
        //退出登录
        async userLogout() {
            //退出登录请求
            let result: any = await reqLogout();
            if (result.code == 200) {
                //目前没有mock接口:退出登录接口(通知服务器本地用户唯一标识失效)
                this.token = '';
                this.username = '';
                this.avatar = '';
                REMOVE_TOKEN();
                return 'ok';
            } else {
                return Promise.reject(new Error(result.message));
            }
        }
    },
    getters: {

    }
})

//对外暴露 获取  '用户 pinia持久化存储(仓库)' 方法
export default useUserStore;